﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using Util.Maps;
using System.Device.Location;
using Microsoft.Devices;
using Microsoft.Phone.Controls.Maps.Platform;
using Util.Json;
using System.Collections.ObjectModel;
using System.IO;

namespace ScotiabankWP7.Forms.AgenciasCajeros
{
    public partial class UbicarAgenciasYCajeros : PhoneApplicationPage
    {

        IGeoPositionWatcher<GeoCoordinate> watcher;

        public UbicarAgenciasYCajeros()
        {
            InitializeComponent();
            //IniciarLocalizacion();
            street.Visibility = Visibility.Visible;
        }
        
        #region Metodos de Localizacion

        private void IniciarLocalizacion()
        {
            if (watcher == null)
            {
                watcher = PickDeviceGeoPositionWatcher();
                watcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(watcher_StatusChanged);
                watcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(watcher_PositionChanged);
                watcher.Start();
            }
        }

        private static IGeoPositionWatcher<GeoCoordinate> PickDeviceGeoPositionWatcher()
        {
            if (Microsoft.Devices.Environment.DeviceType == DeviceType.Device)
            {
                return new GeoCoordinateWatcher(GeoPositionAccuracy.Default);
            }
            else
            {
                GeoCoordinateEventMock[] events = new GeoCoordinateEventMock[] {
                    new  GeoCoordinateEventMock { Latitude=-12.03443, Longitude=-76.96612, Time=new TimeSpan(0,0,5) },
                    new  GeoCoordinateEventMock { Latitude=-12.03427, Longitude=-76.96676, Time=new TimeSpan(0,0,1) },
                    new  GeoCoordinateEventMock { Latitude=-12.03455, Longitude=-76.96643, Time=new TimeSpan(0,0,2) },
                    new  GeoCoordinateEventMock { Latitude=-12.03410, Longitude=-76.96627, Time=new TimeSpan(0,0,3) },
                    new  GeoCoordinateEventMock { Latitude=-12.03489, Longitude=-76.96682, Time=new TimeSpan(0,0,4) },
                    new  GeoCoordinateEventMock { Latitude=-12.03439, Longitude=-76.96699, Time=new TimeSpan(0,0,5) },
                    new  GeoCoordinateEventMock { Latitude=-12.03425, Longitude=-76.96676, Time=new TimeSpan(0,0,6) },
                    new  GeoCoordinateEventMock { Latitude=-12.03469, Longitude=-76.96634, Time=new TimeSpan(0,0,7) }
                };

                return new EventListGeoLocationMock(events);
            }
        }

        void watcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
        {
            Deployment.Current.Dispatcher.BeginInvoke(() => MyStatusChanged(e));

        }
        
        void MyStatusChanged(GeoPositionStatusChangedEventArgs e)
        {
            switch (e.Status)
            {
                case GeoPositionStatus.Disabled:
                    // The location service is disabled or unsupported.
                    // Alert the user
                    //StatusTextBlock.Text = "location is unsupported on this device";
                    MessageBox.Show("location is unsupported on this device");
                    break;
                case GeoPositionStatus.Initializing:
                    // The location service is initializing.
                    // Disable the Start Location button
                    //StatusTextBlock.Text = "initializing location service," + accuracyText;
                    MessageBox.Show("initializing location service,");
                    break;
                case GeoPositionStatus.NoData:
                    // The location service is working, but it cannot get location data
                    // Alert the user and enable the Stop Location button
                    //StatusTextBlock.Text = "data unavailable," + accuracyText;
                    MessageBox.Show("data unavailable,");
                    break;
                case GeoPositionStatus.Ready:
                    // The location service is working and is receiving location data
                    // Show the current position and enable the Stop Location button
                    //StatusTextBlock.Text = "receiving data, " + accuracyText;
                    MessageBox.Show("receiving data,");
                    break;

            }
        }

        void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
        {
            Deployment.Current.Dispatcher.BeginInvoke(() => MyPositionChanged(e));
        }

        void MyPositionChanged(GeoPositionChangedEventArgs<GeoCoordinate> e)
        {            
            GeoCoordinate geo = new GeoCoordinate(e.Position.Location.Latitude, e.Position.Location.Longitude);
            googlemap.Center = geo;

        }
        
        #endregion

        public void CalculateRoute(Location startLocation, Location endLocation)
        {
            string url = "http://maps.google.com/maps/api/directions/json?origin={0},{1}&destination={2},{3}&sensor=false&language=es";
                        
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new Uri(string.Format(url, Source.Location.Latitude, Source.Location.Longitude,
                                            Destination.Location.Latitude, Destination.Location.Longitude)));
            request.BeginGetResponse(new AsyncCallback(googleDirections_CallBack), request);            
        }

        private void googleDirections_CallBack(IAsyncResult asynchronousResult)
        {
            HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
            HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
            string resultString;

            using (StreamReader streamReader = new StreamReader(response.GetResponseStream()))
            {
                resultString = streamReader.ReadToEnd();   
            }

            DirectionsResponse direction = JsonHelper.Deserialize<DirectionsResponse>(resultString);

            ObservableCollection<Location> points = new ObservableCollection<Location>();

            points = obtenerLocations(direction);

            this.Dispatcher.BeginInvoke(() =>
            {
                var data = this.DataContext as MapData;
                data.RoutePoints.Clear();
                foreach (var point in points)
                {
                    data.RoutePoints.Add(new GeoCoordinate(point.Latitude, point.Longitude));
                }
            });
        }      

        public static ObservableCollection<Location> obtenerLocations(DirectionsResponse direction)
        {
            ObservableCollection<Location> lista = new ObservableCollection<Location>();
            
            foreach (routes routes in direction.routes)
            {
                legs[] legs = routes.legs;

                foreach (legs leg in legs)
                {
                    steps[] steps = leg.steps;

                    foreach (steps step in steps)
                    {
                        lista.Add(new Location { Latitude = step.start_location.lat, Longitude = step.start_location.lng });
                        lista.Add(new Location { Latitude = step.end_location.lat, Longitude = step.end_location.lng });
                    }
                }
                /*
                bounds bounds = routes.bounds;
                lista.Add(new Location { Latitude = bounds.southwest.lat, Longitude = bounds.southwest.lng });
                lista.Add(new Location { Latitude = bounds.northeast.lat, Longitude = bounds.northeast.lng });
                */
            }

            return lista;
        }

        #region Metodos de Zoom

        private void ButtonZoomIn_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            googlemap.ZoomLevel++;
        }

        private void ButtonZoomOut_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            googlemap.ZoomLevel--;
        }

        #endregion

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            CalculateRoute(Source.Location, Destination.Location);
        }      
    }
}